using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Google.Protobuf;
using System.Threading.Tasks;
using GamePlay.Features.Shared;
using NativeWebSocket;
using GamePlay.Framework.Events;
using GamePlay.Framework.Timer;
using Com.Lin.Proto;

namespace GamePlay.Framework.Network
{
    /// <summary>
    /// WebSocket消息处理器，优化用于微信平台
    /// 支持Protobuf序列化和反序列化
    /// </summary>
    public class WebSocketMessageHandler : MonoBehaviour
    {
        #region 单例实现

        private static WebSocketMessageHandler _instance;

        public static WebSocketMessageHandler Instance
        {
            get
            {
                if (_instance == null)
                {
                    GameObject obj = GameObject.Find("WebSocketClient")?.gameObject;
                    if (obj == null)
                    {
                        obj = new GameObject("WebSocketClient");
                        DontDestroyOnLoad(obj);
                    }

                    _instance = obj.GetComponent<WebSocketMessageHandler>();
                    if (_instance == null)
                    {
                        _instance = obj.AddComponent<WebSocketMessageHandler>();
                    }
                }
                return _instance;
            }
        }

        #endregion

        #region 字段和属性

        [Header("调试设置")]
        [SerializeField] private bool debugMode = true;

        private WebSocketClientWX webSocketClient;

        // 消息ID到类型的映射字典
        private Dictionary<int, Type> messageTypeMap = new Dictionary<int, Type>();

        #endregion

        #region 生命周期方法

        protected void Awake()
        {
            if (_instance != null && _instance != this)
            {
                Destroy(this);
                return;
            }

            _instance = this;

            // 获取或创建WebSocketClientWX
            webSocketClient = WebSocketClientWX.Instance;

            // 注册WebSocket事件 
            webSocketClient.OnTextMessageReceived += HandleTextMessage;
            webSocketClient.OnBinaryMessageReceived += HandleBinaryMessage;

            // 初始化消息映射
            InitializeWithMessageMapper();

            LogInfo("WebSocketMessageHandler 初始化完成 (微信平台)");
        }

        protected void OnDestroy()
        {
            if (webSocketClient != null)
            {
                webSocketClient.OnTextMessageReceived -= HandleTextMessage;
                webSocketClient.OnBinaryMessageReceived -= HandleBinaryMessage;
            }
        }

        #endregion

        #region 公共方法

        /// <summary>
        /// 注册消息类型，将消息ID映射到对应的Protobuf消息类型
        /// </summary>
        public void RegisterMessageType<T>(int messageId) where T : IMessage
        {
            if (!messageTypeMap.ContainsKey(messageId))
            {
                messageTypeMap.Add(messageId, typeof(T));
                LogInfo($"注册消息类型: ID={messageId}, 类型={typeof(T).Name}");
            }
            else
            {
                LogWarning($"消息类型已存在: ID={messageId}, 现有类型={messageTypeMap[messageId].Name}, 将被替换为={typeof(T).Name}");
                messageTypeMap[messageId] = typeof(T);
            }
        }

        /// <summary>
        /// 使用RequestMsg基础包发送Protobuf消息
        /// </summary>
        public async void SendProtobufMessageWithRequestMsg<T>(int cmd, T message, bool needWaiting = true, Action<bool> callback = null) where T : IMessage
        {
            if (webSocketClient == null || !webSocketClient.IsConnected)
            {
                LogError("无法发送消息：WebSocket未连接");
                callback?.Invoke(false);
                return;
            }

            try
            {
                // 序列化消息
                byte[] messageBytes = message.ToByteArray();

                // 打印消息体大小
                LogInfo($"[消息大小] 准备发送消息CMD={cmd}, 消息体大小={messageBytes.Length}字节");

                // 使用SendRequestMessage发送
                SendRequestMessage(cmd, messageBytes, needWaiting, callback);
            }
            catch (Exception ex)
            {
                LogError($"构建Protobuf消息失败: {ex.Message}");
                callback?.Invoke(false);
            }
        }

        /// <summary>
        /// 发送Protobuf消息（现在内部使用RequestMsg基础包）
        /// </summary>
        public void SendProtobufMessage<T>(int messageId, T message, bool needWaiting = true, Action<bool> callback = null) where T : IMessage
        {
            // 调用使用RequestMsg发送的方法
            SendProtobufMessageWithRequestMsg(messageId, message, needWaiting, callback);
        }

        /// <summary>
        /// 发送请求消息，使用RequestMsg格式
        /// </summary>
        public async void SendRequestMessage(int cmd, byte[] body, bool needWaiting = true, Action<bool> callback = null)
        {
            try
            {
                // 打印原始body大小
                LogInfo($"[消息大小] 原始请求体大小={body?.Length ?? 0}字节, CMD={cmd}");

                // 创建RequestMsg
                var requestMsg = new RequestMsg
                {
                    Cmd = cmd,
                    Seq = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
                    Body = Google.Protobuf.ByteString.CopyFrom(body ?? new byte[0])
                };

                // 序列化消息
                byte[] messageBytes = requestMsg.ToByteArray();

                // 打印RequestMsg序列化后大小
                LogInfo($"[消息大小] 序列化后RequestMsg大小={messageBytes.Length}字节");

                // 直接发送Protobuf序列化的消息，不添加自定义头部
                bool success = false;
                if (webSocketClient != null && webSocketClient.IsConnected)
                {
                    success = await webSocketClient.SendBinaryAsync(messageBytes);
                    Waiting(cmd, needWaiting, success);
                }
                else
                {
                    LogError("无法发送消息：WebSocket未连接");
                }

                callback?.Invoke(success);
            }
            catch (Exception ex)
            {
                LogError($"发送请求消息失败: {ex.Message}");
                callback?.Invoke(false);
            }
        }

        #endregion

        #region 私有方法

        /// <summary>
        /// 处理接收到的文本消息
        /// </summary>
        private void HandleTextMessage(string text)
        {
            if (debugMode)
            {
                LogInfo($"收到文本消息: {text}");
            }

            try
            {
                // 创建文本消息事件参数
                TextMessageEventArgs textEventArgs = new TextMessageEventArgs(text);

                // 发送消息
                Emit(textEventArgs);

                // 尝试解析为JSON也发送特定格式化事件
                try
                {
                    JsonMessageEventArgs jsonEventArgs = new JsonMessageEventArgs(text);
                    Emit(jsonEventArgs);
                }
                catch (Exception jsonEx)
                {
                    if (debugMode)
                    {
                        LogWarning($"JSON解析失败，仅作为文本处理: {jsonEx.Message}");
                    }
                }
            }
            catch (Exception e)
            {
                LogError($"处理文本消息失败: {e.Message}");
            }
        }

        /// <summary>
        /// 处理接收到的二进制消息 - 直接解析为ResponseMsg
        /// </summary>
        private void HandleBinaryMessage(byte[] data)
        {
            if (data == null || data.Length == 0)
            {
                LogError($"接收到的二进制消息为空或长度为0");
                return;
            }

            try
            {
                // 直接尝试解析为ResponseMsg
                ResponseMsg responseMsg = ResponseMsg.Parser.ParseFrom(data);

                if (responseMsg != null)
                {
                    if (debugMode)
                    {
                        LogInfo($"收到二进制消息: CMD={responseMsg.Cmd}, SEQ={responseMsg.Seq}, Body大小={responseMsg.Body.Length}字节");

                        // 打印完整ResponseMsg内容
                        LogInfo($"ResponseMsg详细信息: \n" +
                               $"  CMD: {responseMsg.Cmd}\n" +
                               $"  SEQ: {responseMsg.Seq}\n" +
                               $"  ErrorCode: {responseMsg.ErrorCode}\n" +
                               $"  Body大小: {responseMsg.Body.Length}字节");

                        // 打印选项
                        if (responseMsg.Opt.Count > 0)
                        {
                            string optString = "";
                            foreach (var opt in responseMsg.Opt)
                            {
                                optString += $"{opt.Key}={opt.Value}, ";
                            }
                            optString = optString.TrimEnd(',', ' ');
                            LogInfo($"  Opt选项: {optString}");
                        }
                        else
                        {
                            LogInfo($"  Opt选项: 无");
                        }
                    }

                    Waiting(responseMsg.Cmd, true, false);

                    // 使用消息映射器解析和发送事件
                    var mapper = ProtobufMessageMapper.Instance;

                    // 检查是否可以基于子消息进行处理
                    if (mapper.IsMessageRegistered(responseMsg.Cmd))
                    {
                        // 如果Body为空，可能是服务器直接使用ResponseMsg作为消息本身，不含嵌套消息
                        if (responseMsg.Body.Length == 0)
                        {
                            LogInfo($"收到空Body的ResponseMsg，CMD={responseMsg.Cmd}，将直接处理");

                            // 特殊处理登录消息
                            if (responseMsg.Cmd == -100101)
                            {
                                // 创建一个默认的登录响应
                                var loginResponse = new ResLoginMessage
                                {
                                    LoginSuccess = responseMsg.ErrorCode == Com.Lin.Proto.ErrorCode.ErrorNone,
                                    PlayerId = 0
                                };

                                // 如果ResponseMsg的opt中有会话ID，则设置
                                if (responseMsg.Opt.ContainsKey(1))
                                {
                                    loginResponse.SessionId = responseMsg.Opt[1];
                                }

                                // 输出创建的登录响应对象
                                LogInfo($"创建登录响应: LoginSuccess={loginResponse.LoginSuccess}, PlayerId={loginResponse.PlayerId}, SessionId={loginResponse.SessionId ?? "未设置"}");

                                // 创建事件参数并发送
                                var eventArgs = new LoginResponseEventArgs(loginResponse);
                                Emit(eventArgs);
                                return;
                            }
                        }

                        var subEventArgs = mapper.ParseMessage(responseMsg.Cmd, responseMsg.Body.ToByteArray());
                        if (subEventArgs != null)
                        {
                            // 针对不同类型的消息进行特殊处理和打印
                            if (subEventArgs is LoginResponseEventArgs loginArgs)
                            {
                                LogInfo($"解析到登录响应消息: LoginSuccess={loginArgs.Data.LoginSuccess}, " +
                                      $"PlayerId={loginArgs.Data.PlayerId}, SessionId={loginArgs.Data.SessionId ?? "未设置"}");
                            }
                            else
                            {
                                LogInfo($"解析到消息类型: {subEventArgs.GetType().Name}");
                            }

                            Emit(subEventArgs);
                        }
                    }
                    else
                    {
                        if (debugMode)
                        {
                            LogWarning($"未找到消息注册: CMD={responseMsg.Cmd}");
                        }
                    }
                }
            }
            catch (Exception e)
            {
                LogError($"处理二进制消息失败: {e.Message}");

                // 添加额外的调试信息
                if (debugMode && data.Length >= 16)
                {
                    string dataHex = BitConverter.ToString(data, 0, Math.Min(32, data.Length)).Replace("-", " ");
                    LogError($"二进制数据内容(前32字节): {dataHex}");
                }
            }
        }

        private void LogInfo(string message)
        {
            if (debugMode)
                Debug.Log($"[WebSocketMessageHandler] {message}");
        }

        private void LogWarning(string message)
        {
            Debug.LogWarning($"[WebSocketMessageHandler] {message}");
        }

        private void LogError(string message)
        {
            Debug.LogError($"[WebSocketMessageHandler] {message}");
        }

        private void Emit<T>(T data) where T : EventArgs
        {
            EventManager.Instance.RaiseEvent<T>(this, data);
        }

        private void Waiting(int messageId, bool need, bool waiting)
        {
            if (need)
            {
                // 使用事件系统发送网络等待状态
                Emit(new NetworkWaiting { waiting = waiting, messageId = messageId });
            }
        }

        #endregion

        #region 事件参数类

        [Serializable]
        public class RawBinaryEventArgs : EventArgs
        {
            public int MessageId { get; set; }
            public byte[] RawBytes { get; set; }
        }

        [Serializable]
        public class NetworkWaiting : EventArgs
        {
            public bool waiting;
            public int messageId;
        }

        [Serializable]
        public class TextMessageEventArgs : EventArgs
        {
            public string Text { get; private set; }

            public TextMessageEventArgs(string text)
            {
                Text = text;
            }
        }

        [Serializable]
        public class JsonMessageEventArgs : EventArgs
        {
            public string JsonText { get; private set; }

            public JsonMessageEventArgs(string jsonText)
            {
                JsonText = jsonText;
            }

            public T ParseAs<T>() where T : class
            {
                try
                {
                    return UnityEngine.JsonUtility.FromJson<T>(JsonText);
                }
                catch
                {
                    return null;
                }
            }
        }

        #endregion

        /// <summary>
        /// 初始化消息映射
        /// </summary>
        public static void InitializeWithMessageMapper()
        {
            Debug.Log("[WebSocketMessageHandler] 开始初始化消息映射...");

            // 注册所有消息类型
            ProtobufMessageRegister.RegisterAllMessages();

            Debug.Log("[WebSocketMessageHandler] 消息映射初始化完成");
        }
    }
}